home *** CD-ROM | disk | FTP | other *** search
/ Ham Radio 2000 / Ham Radio 2000.iso / ham2000 / tcp_ip / os2 / pmnos11s / tcpcmd.c < prev    next >
C/C++ Source or Header  |  1993-07-30  |  10KB  |  445 lines

  1. /* TCP control and status routines
  2.  * Copyright 1991 Phil Karn, KA9Q
  3.  *
  4.  * Mods by G1EMM
  5.  */
  6. #include <stdio.h>
  7. #if !defined(OS2)
  8. #include <dos.h>
  9. #endif
  10. #include "global.h"
  11. #include "timer.h"
  12. #include "mbuf.h"
  13. #include "netuser.h"
  14. #include "internet.h"
  15. #include "tcp.h"
  16. #include "cmdparse.h"
  17. #include "commands.h"
  18.  
  19. static int doirtt __ARGS((int argc,char *argv[],void *p));
  20. static int domss __ARGS((int argc,char *argv[],void *p));
  21. static int dortt __ARGS((int argc,char *argv[],void *p));
  22. static int dotcpkick __ARGS((int argc,char *argv[],void *p));
  23. static int dotcpreset __ARGS((int argc,char *argv[],void *p));
  24. static int dotcpretries __ARGS((int argc,char *argv[],void *p));
  25. static int dotcpstat __ARGS((int argc,char *argv[],void *p));
  26. static int dotcptimer __ARGS((int argc,char *argv[],void *p));
  27. static int dotcptr __ARGS((int argc,char *argv[],void *p));
  28. static int dowindow __ARGS((int argc,char *argv[],void *p));
  29. static int dosyndata __ARGS((int argc,char *argv[],void *p));
  30. static int doview __ARGS((int argc,char *argv[],void *p));
  31. void rxtx_data_compute __ARGS((struct tcb *tcb,int32 *sent,int32 *recvd));
  32. static int tstat __ARGS((void));
  33.  
  34. /* TCP subcommand table */
  35. static struct cmds Tcpcmds[] = {
  36.     "irtt",        doirtt,        0, 0,    NULLCHAR,
  37.     "kick",        dotcpkick,    0, 2,    "tcp kick <tcb>",
  38.     "mss",        domss,        0, 0,    NULLCHAR,
  39.     "reset",    dotcpreset,    0, 2,    "tcp reset <tcb>",
  40.     "retries",  dotcpretries,0,0,   NULLCHAR,
  41.     "rtt",      dortt,      0, 3,   "tcp rtt <tcb> <val>",
  42.     "status",    dotcpstat,    0, 0,    NULLCHAR,
  43.     "syndata",    dosyndata,    0, 0,    NULLCHAR,
  44.     "timertype",    dotcptimer,    0, 0,    NULLCHAR,
  45.     "trace",    dotcptr,    0, 0,    NULLCHAR,
  46.     "view",     doview,     0, 0,   NULLCHAR,
  47.     "window",   dowindow,   0, 0,   NULLCHAR,
  48.     NULLCHAR,
  49. };
  50. int
  51. dotcp(argc,argv,p)
  52. int argc;
  53. char *argv[];
  54. void *p;
  55. {
  56.     return subcmd(Tcpcmds,argc,argv,p);
  57. }
  58. static int
  59. dotcptr(argc,argv,p)
  60. int argc;
  61. char *argv[];
  62. void *p;
  63. {
  64.     return setbool(&Tcp_trace,"TCP state tracing",argc,argv);
  65. }
  66.  
  67. /* Eliminate a TCP connection */
  68. static int
  69. dotcpreset(argc,argv,p)
  70. int argc;
  71. char *argv[];
  72. void *p;
  73. {
  74.     struct tcb *tcb;
  75.  
  76. #if !defined(OS2)
  77.     tcb = MK_FP(htoi(argv[1]),8);
  78. #else
  79.     tcb = (struct tcb *)htoi(argv[1]);
  80. #endif
  81.     if(!tcpval(tcb)){
  82.         tprintf(Notval);
  83.         return 1;
  84.     }
  85.     reset_tcp(tcb);
  86.     return 0;
  87. }
  88.  
  89. /* Set initial round trip time for new connections */
  90. static int
  91. doirtt(argc,argv,p)
  92. int argc;
  93. char *argv[];
  94. void *p;
  95. {
  96.     struct tcp_rtt *tp;
  97.  
  98.     setlong(&Tcp_irtt,"TCP default irtt",argc,argv);
  99.     if(argc < 2){
  100.         for(tp = &Tcp_rtt[0];tp < &Tcp_rtt[RTTCACHE];tp++){
  101.             if(tp->addr != 0){
  102.                 if(tprintf("%s: srtt %lu mdev %lu\n",
  103.                  inet_ntoa(tp->addr),
  104.                  tp->srtt,tp->mdev) == EOF)
  105.                     break;
  106.             }
  107.         }
  108.     }
  109.     return 0;
  110. }
  111.  
  112. extern int16 Tcp_retries;
  113.  
  114. /* Set maximum number of backoffs before resetting the connection */
  115. static int
  116. dotcpretries(argc,argv,p)
  117. int argc;
  118. char *argv[];
  119. void *p;
  120. {
  121.     return setshort(&Tcp_retries,"max. retries",argc,argv);
  122. }
  123.  
  124.  
  125. /* Set smoothed round trip time for specified TCB */
  126. static int
  127. dortt(argc,argv,p)
  128. int argc;
  129. char *argv[];
  130. void *p;
  131. {
  132.     register struct tcb *tcb;
  133.  
  134.     tcb = (struct tcb *)ltop(htol(argv[1]));
  135.     if(!tcpval(tcb)){
  136.         tprintf(Notval);
  137.         return 1;
  138.     }
  139.     tcb->srtt = atol(argv[2]);
  140.     return 0;
  141. }
  142.  
  143. /* Force a retransmission */
  144. static int
  145. dotcpkick(argc,argv,p)
  146. int argc;
  147. char *argv[];
  148. void *p;
  149. {
  150.     struct tcb *tcb;
  151.  
  152. #if !defined(OS2)
  153.     tcb = MK_FP(htoi(argv[1]),8);
  154. #else
  155.     tcb = (struct tcb *)htoi(argv[1]);
  156. #endif
  157.     if(kick_tcp(tcb) == -1){
  158.         tprintf(Notval);
  159.         return 1;
  160.     }
  161.     return 0;
  162. }
  163.  
  164. /* Set default maximum segment size */
  165. static int
  166. domss(argc,argv,p)
  167. int argc;
  168. char *argv[];
  169. void *p;
  170. {
  171.     return setshort(&Tcp_mss,"TCP MSS",argc,argv);
  172. }
  173.  
  174. /* Set default window size */
  175. static int
  176. dowindow(argc,argv,p)
  177. int argc;
  178. char *argv[];
  179. void *p;
  180. {
  181.     return setshort(&Tcp_window,"TCP window",argc,argv);    
  182. }
  183.  
  184. static int
  185. dosyndata(argc,argv,p)
  186. int argc;
  187. char *argv[];
  188. void *p;
  189. {
  190.     return setbool(&Tcp_syndata,"TCP syn+data piggybacking",argc,argv);
  191. }
  192.  
  193.  
  194. /* Display status of TCBs */
  195. static int
  196. dotcpstat(argc,argv,p)
  197. int argc;
  198. char *argv[];
  199. void *p;
  200. {
  201.     struct tcb *tcb;
  202.  
  203.     if(argc < 2){
  204.         tstat();
  205.     } else {
  206.  
  207. #if !defined(OS2)
  208.     tcb = MK_FP(htoi(argv[1]),8);
  209. #else
  210.     tcb = (struct tcb *)htoi(argv[1]);
  211. #endif
  212.         if(!tcpval(tcb))
  213.             tprintf(Notval);
  214.         else
  215.             st_tcp(tcb);
  216.     }
  217.     return 0;
  218. }
  219.  
  220. /* Dump TCP stats and summary of all TCBs
  221. /*     &TCB Rcv-Q Snd-Q  Local socket           Remote socket          State
  222.  *     1234     0     0  xxx.xxx.xxx.xxx:xxxxx  xxx.xxx.xxx.xxx:xxxxx  Established
  223.  */
  224. static int
  225. tstat()
  226. {
  227.     register int i;
  228.     register struct tcb *tcb;
  229.     int j;
  230.  
  231.     for(j=i=1;i<=NUMTCPMIB;i++){
  232.         if(Tcp_mib[i].name == NULLCHAR)
  233.             continue;
  234.         tprintf("(%2u)%-20s%10lu",i,Tcp_mib[i].name,
  235.          Tcp_mib[i].value.integer);
  236.         if(j++ % 2)
  237.             tprintf("     ");
  238.         else
  239.             tprintf("\n");
  240.     }
  241.     if((j % 2) == 0)
  242.         tprintf("\n");
  243. #if !defined(OS2)
  244.     tprintf("&TCB Rcv-Q Snd-Q  Local socket           Remote socket          State\n");
  245. #else
  246.     tprintf("&TCB     Rcv-Q Snd-Q  Local socket           Remote socket          State\n");
  247. #endif
  248.     for(tcb=Tcbs;tcb != NULLTCB;tcb = tcb->next){
  249. #if !defined(OS2)
  250.         tprintf("%4.4x%6u%6u  ",FP_SEG(tcb),tcb->rcvcnt,tcb->sndcnt);
  251. #else
  252.         tprintf("%8x%6u%6u  ",ptol(tcb),tcb->rcvcnt,tcb->sndcnt);
  253. #endif
  254.         tprintf("%-23s",pinet(&tcb->conn.local));
  255.         tprintf("%-23s",pinet(&tcb->conn.remote));
  256.         tprintf("%-s",Tcpstates[tcb->state]);
  257.         if(tcb->state == TCP_LISTEN && tcb->flags.clone)
  258.             tprintf(" (S)");
  259.         if(tprintf("\n") == EOF)
  260.             return 0;
  261.     }
  262.     return 0;
  263. }
  264. /* Dump a TCP control block in detail */
  265. void
  266. st_tcp(tcb)
  267. struct tcb *tcb;
  268. {
  269.     int32 sent,recvd;
  270.  
  271.     if(tcb == NULLTCB)
  272.         return;
  273.  
  274.     rxtx_data_compute(tcb,&sent,&recvd);
  275.  
  276.     tprintf("Local: %s",pinet(&tcb->conn.local));
  277.     tprintf(" Remote: %s",pinet(&tcb->conn.remote));
  278.     tprintf(" State: %s\n",Tcpstates[tcb->state]);
  279.     tprintf("      Init seq    Unack     Next Resent CWind Thrsh  Wind  MSS Queue      Total\n");
  280.     tprintf("Send:");
  281.     tprintf("%9lx",tcb->iss);
  282.     tprintf("%9lx",tcb->snd.una);
  283.     tprintf("%9lx",tcb->snd.nxt);
  284.     tprintf("%7lu",tcb->resent);
  285.     tprintf("%6u",tcb->cwind);
  286.     tprintf("%6u",tcb->ssthresh);
  287.     tprintf("%6u",tcb->snd.wnd);
  288.     tprintf("%5u",tcb->mss);
  289.     tprintf("%6u",tcb->sndcnt);
  290.     tprintf("%11lu\n",sent);
  291.  
  292.     tprintf("Recv:");
  293.     tprintf("%9lx",tcb->irs);
  294.     tprintf("         ");
  295.     tprintf("%9lx",tcb->rcv.nxt);
  296.     tprintf("%7lu",tcb->rerecv);
  297.     tprintf("      ");
  298.     tprintf("      ");
  299.     tprintf("%6u",tcb->rcv.wnd);
  300.     tprintf("     ");
  301.     tprintf("%6u",tcb->rcvcnt);
  302.     tprintf("%11lu\n",recvd);
  303.  
  304.     if(tcb->reseq != (struct reseq *)NULL){
  305.         register struct reseq *rp;
  306.  
  307.         tprintf("Reassembly queue:\n");
  308.         for(rp = tcb->reseq;rp != (struct reseq *)NULL; rp = rp->next){
  309.             if(tprintf("  seq x%lx %u bytes\n",
  310.              rp->seg.seq,rp->length) == EOF)
  311.                 return;
  312.         }
  313.     }
  314.     if(tcb->backoff > 0)
  315.         tprintf("Backoff %u ",tcb->backoff);
  316.     if(tcb->flags.retran)
  317.         tprintf("Retrying ");
  318.     switch(tcb->timer.state){
  319.     case TIMER_STOP:
  320.         tprintf("Timer stopped ");
  321.         break;
  322.     case TIMER_RUN:
  323.         tprintf("Timer running (%ld/%ld ms) ",
  324.          (long)read_timer(&tcb->timer),
  325.          (long)dur_timer(&tcb->timer));
  326.         break;
  327.     case TIMER_EXPIRE:
  328.         tprintf("Timer expired ");
  329.     }
  330.     tprintf("SRTT %ld ms Mean dev %ld ms\n",tcb->srtt,tcb->mdev);
  331. }
  332.  
  333. void
  334. rxtx_data_compute(tcb,sent,recvd)
  335. struct tcb *tcb;
  336. int32 *sent;
  337. int32 *recvd;
  338. {
  339.  
  340.     /* Compute total data sent and received; take out SYN and FIN */
  341.     *sent = tcb->snd.una - tcb->iss;    /* Acknowledged data only */
  342.     *recvd = tcb->rcv.nxt - tcb->irs;
  343.     switch(tcb->state){
  344.     case TCP_LISTEN:
  345.     case TCP_SYN_SENT:    /* Nothing received or acked yet */
  346.         *sent = *recvd = 0;    
  347.         break;
  348.     case TCP_SYN_RECEIVED:
  349.         (*recvd)--;    /* Got SYN, no data acked yet */
  350.         *sent = 0;
  351.         break;
  352.     case TCP_ESTABLISHED:    /* Got and sent SYN */
  353.     case TCP_FINWAIT1:    /* FIN not acked yet */
  354.         (*sent)--;
  355.         (*recvd)--;
  356.         break;
  357.     case TCP_FINWAIT2:    /* Our SYN and FIN both acked */
  358.         *sent -= 2;
  359.         (*recvd)--;
  360.         break;
  361.     case TCP_CLOSE_WAIT:    /* Got SYN and FIN, our FIN not yet acked */
  362.     case TCP_CLOSING:
  363.     case TCP_LAST_ACK:
  364.         (*sent)--;
  365.         *recvd -= 2;
  366.         break;
  367.     case TCP_TIME_WAIT:    /* Sent and received SYN/FIN, all acked */
  368.         *sent -= 2;
  369.         *recvd -= 2;
  370.         break;
  371.     }
  372. }
  373.  
  374. static int
  375. doview()
  376. {
  377.     register struct tcb *tcb;
  378.     int32 sent,recvd;
  379.     char temp[40];
  380. #if !defined(PM)
  381.     tprintf("                                               Send  Send      Receive  Receive\n");
  382.     tprintf("&TCB Remote Socket:Port:Local Port/State       Bytes Retries     Bytes  Retries\n");
  383. #else
  384.     tprintf("                                                   Send  Send      Receive  Receive\n");
  385.     tprintf("&TCB     Remote Socket:Port:Local Port/State       Bytes Retries     Bytes  Retries\n");
  386.     for(tcb=Tcbs;tcb != NULLTCB;tcb = tcb->next){
  387. #endif
  388.         if(tcb->state == TCP_LISTEN)
  389.             continue;
  390.         
  391.         sprintf(temp,"%8lx  ",ptol(tcb));
  392. #if !defined(PM)
  393.         temp[4]=0;
  394.         tprintf("%-4s ",temp);
  395. #else
  396.         tprintf("%-8s ",temp);
  397. #endif
  398.         strcpy(temp,pinet(&tcb->conn.remote));
  399.         strcat(temp,strstr(pinet(&tcb->conn.local),":"));
  400.         strcat(temp,"/");
  401.         strcat(temp,Tcpstates[tcb->state]);
  402.         tprintf("%-37s",temp);
  403.         rxtx_data_compute(tcb,&sent,&recvd);
  404.         tprintf("%10lu ",sent);
  405.         tprintf("%7lu ",tcb->resent);
  406.         tprintf("%10lu ",recvd);
  407.         tprintf("%7lu",tcb->rerecv);
  408.         if(tprintf("\n") == EOF)
  409.             return 0;
  410.     }
  411.     return 0;
  412. }
  413.  
  414. /* tcp timers type - linear v exponential */
  415. static
  416. dotcptimer(argc,argv,p)
  417. int argc ;
  418. char *argv[] ;
  419. void *p ;
  420. {
  421.     extern int tcptimertype;
  422.  
  423.     if (argc < 2) {
  424.         tprintf("Tcp timer type is %s\n", tcptimertype ? "linear" : "exponential" ) ;
  425.         return 0 ;
  426.     }
  427.     
  428.     switch (argv[1][0]) {
  429.         case 'l':
  430.         case 'L':
  431.             tcptimertype = 1 ;
  432.             break ;
  433.         case 'e':
  434.         case 'E':
  435.             tcptimertype = 0 ;
  436.             break ;
  437.         default:
  438.             tprintf("use: tcp timertype [linear|exponential]\n") ;
  439.             return -1 ;
  440.     }
  441.  
  442.     return 0 ;
  443. }
  444.  
  445.